package com.aiden.app.common.view

import android.animation.ObjectAnimator
import android.content.Context
import android.support.annotation.DrawableRes
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.animation.DecelerateInterpolator
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.TextView
import com.aiden.app.common.R
import com.aiden.app.common.extension.setVisible

class DragFloatingActionButton : FrameLayout {

    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

    init {
        val view = View.inflate(context, R.layout.layout_floating, null)
        ivFloat = view.findViewById(R.id.iv_float)
        tvCount = view.findViewById(R.id.tv_count)
        addView(view)
    }

    private var lastX = 0
    private var lastY = 0
    private var parentHeight = 0
    private var parentWidth = 0
    private var isDrag = false
    private var ivFloat: ImageView
    private var tvCount: TextView
    private var count = 0
    private var startX = 0
    private var startY = 0

    override fun onTouchEvent(event: MotionEvent): Boolean {
        val rawX = event.rawX.toInt()
        val rawY = event.rawY.toInt()

        when (event.action and MotionEvent.ACTION_MASK) {
            MotionEvent.ACTION_DOWN -> {
                isPressed = true
                isDrag = false
                parent.requestDisallowInterceptTouchEvent(true)
                startX = rawX
                startY = rawY
                lastX = rawX
                lastY = rawY
                val parent: ViewGroup
                if (getParent() != null) {
                    parent = getParent() as ViewGroup
                    parentHeight = parent.height
                    parentWidth = parent.width
                }
            }
            MotionEvent.ACTION_MOVE -> {
                isDrag = !(parentHeight <= 0 || parentWidth == 0)
                val dx = rawX - lastX
                val dy = rawY - lastY

                val distance = Math.sqrt((dx * dx + dy * dy).toDouble()).toInt()
                if (distance == 0) {
                    isDrag = false
                } else {
                    var x = x + dx
                    var y = y + dy

                    // 检测是否到达边缘
                    x = if (x < 0) 0f else if (x > parentWidth - width) (parentWidth - width).toFloat() else x
                    y = if (getY() < 0) 0f else if (getY() + height > parentHeight) (parentHeight - height).toFloat() else y
                    setX(x)
                    setY(y)
                    lastX = rawX
                    lastY = rawY
                }
            }
            MotionEvent.ACTION_UP -> {
                val dx = (event.rawX - startX).toInt()
                val dy = (event.rawY - startY).toInt()
                if (Math.abs(dx) < 10 && Math.abs(dy) < 10) {
                    performClick()
                } else {
                    isPressed = false
                    if (rawX >= parentWidth / 2) {
                        animate().setInterpolator(DecelerateInterpolator())
                                .setDuration(300)
                                .xBy(parentWidth - width - x)
                                .start()
                    } else {
                        val oa = ObjectAnimator.ofFloat(this, "x", x, 0f)
                        oa.interpolator = DecelerateInterpolator()
                        oa.duration = 300
                        oa.start()
                    }
                }
            }
        }

        return !isDrag
    }

    fun setImageResource(@DrawableRes iconRes: Int) {
        ivFloat.setImageResource(iconRes)
    }

    fun setCount(count: Int) {
        this.count = count
        if (count > 0) {
            tvCount.setVisible(true)
            tvCount.text = "$count"
        } else {
            tvCount.setVisible(false)
        }
    }

    private fun isNotDrag(): Boolean {
        return !isDrag && (x == 0f || x == (parentWidth - width).toFloat())
    }
}